/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cn.ac.iie.di.zhihu.gkfb.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPOutputStream;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.log4j.Logger;
import sun.misc.BASE64Encoder;

/**
 *
 * @author Administrator
 */
public class HttpsPost {

    private static Logger logger = Logger.getLogger(HttpsPost.class.getName());

    public static void main(String[] args) {
        try {
//            long timestamp = 1507625190;

            long timestamp = System.currentTimeMillis();
            logger.info("timestamp = " + timestamp);
            String uri = "/govern"; //uri；test/后面为数字随意
            logger.info("uri = " + uri);
            //生成签名
            String secret = "#1zl3otqyh0rig2=TXbq+ZZZ6UHd2TxX7QaERqrkRt5";//测试用密钥
            logger.info("secret = " + secret);
            String sign = getSignature(timestamp, uri, secret);
            logger.info("sign = " + sign);
            //将生成的签名以及调用时的时间戳通过 HTTP header 和请求一同进行接口调用
            //测试发送https
            String request
                    = "{"
                    + "\"cmd_id\":\"233728992\","
                    + "\"cmd_type\":\"control\","
                    + "\"cmd_content\":"
                    + "{\"cmd_action\":\"019\","
                    + "\"cmd_params\":"
                    + "{\"answer_id\":\"233728992\"}}}";
//            String httpsUrl = "http://loliyccacclti.zhihu.com/test/12345";//知乎的请求地址，等待确认
            String httpsUrl = "http://loliyccacclti.zhihu.com/govern";
//            String httpsUrl = "http://127.0.0.1:8080/cmdControl/cmdCommit";
            String queryRequest = "{"
                    + "\"cmd_id\":\"1\","
                    + "\"cmd_type\":\"query\","
                    + "\"cmd_content\":{"
                    + "\"cmd_action\":\"003\","
                    + "\"cmd_params\":{"
                    + "\"user_id\":\"ea61559768951a6a2dbeb07d5d9bb5d3\""
                    + "}"
                    + "}"
                    + "}";
//            String response = sendStringByUrl(request, httpsUrl, sign, timestamp);
            logger.info("url = " + httpsUrl);
            logger.info("request = " + request);
            logger.info("httpUrl = " + httpsUrl);
//            logger.info("response = " + response);
            String querySign = getSignature(timestamp, "/query", "#1zl3otqyh0rig2=TXbq+ZZZ6UHd2TxX7QaERqrkRt5");
            logger.info("queryRequest = " + queryRequest);
//            logger.info(sendStringByUrl(queryRequest, "http://loliyccacclti.zhihu.com/query", querySign, timestamp));
//            logger.info(httpsPost("https://loliyccacclti.zhihu.com/govern", request, sign, timestamp));
        String fbRequest= "{\"cmd_id\":\"1\",\"status\":\"0\",\"time\":\"20171012095402\"}";
            logger.info(httpsPost("https://127.0.0.1:8088/govern/feedback", fbRequest, sign, timestamp));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }
//生成签名

    public static String getSignature(long timestamp, String uri, String secret) throws UnsupportedEncodingException, ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");

        String dateStr = simpleDateFormat.format(timestamp);
        String secret_sign = hmac_sha256(secret, dateStr);
        String base_sign = hmac_sha256(secret_sign, String.valueOf(timestamp / 1000));
        BASE64Encoder encoder = new BASE64Encoder();
        String sign = hmac_sha256(base_sign, encoder.encode(uri.getBytes()));
        return sign;
    }
//使用 hmac_sha256 算法,变成 hex 格式字符串

    public static String hmac_sha256(String secret, String message) {
        logger.info("secret = " + secret + ",message = " + message);
        String hash = "";
        try {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            byte[] bytes = sha256_HMAC.doFinal(message.getBytes());
            hash = Hex.encodeHexString(bytes);
            logger.info("hmac_sha256 = " + hash);
        } catch (Exception e) {
            logger.error("Error HmacSHA256 ===========" + e.getMessage());
        }
        return hash;
    }

//变成 hex 格式字符串
    public static String httpsPost(String httpsUrl, String request, String signature, long requestTime) {
        String responseStr = "";
        HttpPost httppost = null;
        CloseableHttpClient client = null;
        try {

//            byte[] gz = getGZip(request);
            SSLContextBuilder sslcontext = new SSLContextBuilder();
            sslcontext.loadTrustMaterial(null, new TrustSelfSignedStrategy());
            client = HttpClients.custom().
                    setSSLContext(sslcontext.build()).
                    setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
            httppost = new HttpPost(httpsUrl); //IP和端口待定

            //设置header，先写死
            httppost.addHeader("Authorization", "Signature=" + signature + ",RequestTime=" + requestTime / 1000 + ",Source=CAC");
            httppost.addHeader("User-Agent", "CAC User-Agent");
            InputStreamEntity reqEntity = new InputStreamEntity(new ByteArrayInputStream(request.getBytes()), -1);
//            reqEntity.setContentType("binary/octet-stream");
//            reqEntity.setChunked(true);
            httppost.setEntity(reqEntity);
            HttpResponse response = client.execute(httppost);
            StatusLine sl = response.getStatusLine();
            logger.info(sl.getStatusCode());
            if (sl.getStatusCode() == 200) {
                responseStr = getResponseContent(response);
                logger.info(responseStr);
            } else {
                responseStr = getResponseContent(response);
                logger.info("response is not 200"+responseStr);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            httppost.releaseConnection();
            try {
                client.close();
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
        return responseStr;
    }

    public static String sendStringByUrl(String request, String url, String signature, long requestTime) {
        String result = "";
        HttpPost httppost = null;
        CloseableHttpClient httpClient1 = null;
        try {
            //设置超时
            RequestConfig defaultRequestConfig = RequestConfig.custom()
                    .setSocketTimeout(5000)
                    .setConnectTimeout(5000)
                    .setConnectionRequestTimeout(5000)
                    .build();
            httpClient1 = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig).build();
            //设置超时5s
//            httpClient1.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
//            httpClient1.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
            httppost = new HttpPost(url);
//            List<Header> headers = new ArrayList<Header>();
//            headers.add(new BasicHeader("Signature", signature));
//            headers.add(new BasicHeader("RequestTime", String.valueOf(requestTime)));
//            headers.add(new BasicHeader("Source", "CAC"));
            httppost.addHeader("Authorization", "Signature=" + signature + ",RequestTime=" + requestTime / 1000 + ",Source=CAC");
            httppost.addHeader("User-Agent", "CAC User-Agent");
//            logger.info(headers.toString());
            logger.info(httppost.getAllHeaders()[0].toString() + "---------" + httppost.getAllHeaders()[1].toString());
            StringEntity reqEntity = new StringEntity(request, Charset.forName("UTF-8"));
            reqEntity.setContentType("application/json");// 区分不同种类的数据,xml数据
            httppost.setEntity(reqEntity);
            HttpResponse response = httpClient1.execute(httppost);
            StatusLine sl = response.getStatusLine();
            if (sl.getStatusCode() == 200) {
                String rs = HttpResponseParser.getResponseContent(response);
                result = rs;
            } else {
                result = "";
                String rs = HttpResponseParser.getResponseContent(response);
                result = rs;
                logger.warn("response code is " + sl.getStatusCode() + "\nresponse content is \t" + result); //                System.out.println(response.toString());
            }
        } catch (IOException ex) {
            logger.error(ex.getMessage(), ex);
        } finally {
            httppost.releaseConnection();
            httpClient1.getConnectionManager().shutdown();
        }
        return result;
    }

    public static byte[] getGZip(String data) throws IOException {
        byte[] b;
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        GZIPOutputStream gout = new GZIPOutputStream(bout); // buffer
        gout.write(data.getBytes());
        gout.close();
        return bout.toByteArray();
    }

    public static String getResponseContent(HttpResponse response) {

        InputStream reponseStream = null;
        try {
            reponseStream = response.getEntity().getContent();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] bytesContent = new byte[1024];
            int bytesReadIn = 0;

            while ((bytesReadIn = reponseStream.read(bytesContent, 0, 1024)) > 0) {
                out.write(bytesContent, 0, bytesReadIn);
            }
            out.close();
            byte[] rep = out.toByteArray();

            return new String(rep, "UTF-8");
        } catch (Exception ex) {
            return null;
        } finally {
            try {
                reponseStream.close();
            } catch (Exception ex) {
            }
        }
    }

}
